<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { CountUp } from 'countup.js'
import type { CountUpOptions } from 'countup.js'

const props = withDefaults(
  defineProps<{
    endVal: number | string
    startVal?: number | string
    duration?: number | string
    autoplay?: boolean
    loop?: boolean | number | string
    delay?: number
    options?: CountUpOptions
  }>(),
  {
    startVal: 0,
    duration: 2.5,
    autoplay: true,
    loop: false,
    delay: 0,
    options: undefined
  }
)

const emits = defineEmits<{
  (event: 'init', countup: CountUp): void
  (event: 'finished'): void
}>()

let elRef = ref<HTMLElement>()
let countUp = ref<CountUp>()
// 存储转换后的值、单位、小数位数
const formatted = ref<{ value: number; suffix: string; decimalPlaces: number }>({ 
  value: 0, 
  suffix: '', 
  decimalPlaces: 0 
});

// 数值格式化核心函数
const formatNumber = (num: number): { value: number; suffix: string; decimalPlaces: number } => {
  const numVal = Math.floor(num); // 先取整，避免原始数值带小数
  
  if (numVal >= 1000000) {
    // 百万级（m）：1位小数
    return {
      value: Math.floor(numVal / 100000) / 10,
      suffix: 'm',
      decimalPlaces: 1
    };
  } else if (numVal >= 1000) {
    // 千级（k）：1位小数
    return {
      value: Math.floor(numVal / 100) / 10,
      suffix: 'k',
      decimalPlaces: 1
    };
  } else {
    // 千以下：整数（0位小数）
    return {
      value: numVal,
      suffix: '',
      decimalPlaces: 0
    };
  }
};

const initCountUp = () => {
  if (!elRef.value) return;
  const startVal = Number(props.startVal);
  const endVal = Number(props.endVal);
  
  formatted.value = formatNumber(endVal);
  const formattedStart = formatNumber(startVal);
  
  countUp.value = new CountUp(elRef.value, formatted.value.value, {
    startVal: formattedStart.value,
    duration: Number(props.duration),
    decimalPlaces: formatted.value.decimalPlaces, // 动态小数位
    ...props.options
  });
  
  if (countUp.value.error) {
    console.error(countUp.value.error);
    return;
  }
  emits('init', countUp.value);
};

const startAnim = (cb?: () => void) => {
  countUp.value?.start(cb);
};

// 监听endVal变化，同步更新
watch(
  () => props.endVal,
  (value) => {
    if (props.autoplay) {
      const newEndVal = Number(value);
      
      formatted.value = formatNumber(newEndVal);
      countUp.value?.update(formatted.value.value);
      if (countUp.value) {
        countUp.value.options.decimalPlaces = formatted.value.decimalPlaces;
      }
    }
  }
);



// 循环动画逻辑（保持不变）
const finished = ref(false);
let loopCount = 0;
const loopAnim = () => {
  loopCount++;
  startAnim(() => {
    const isTruely = typeof props.loop === 'boolean' && props.loop;
    if (isTruely || props.loop > loopCount) {
      delay(() => {
        countUp.value?.reset();
        loopAnim();
      }, props.delay);
    } else {
      finished.value = true;
    }
  });
};
watch(finished, (flag) => {
  if (flag) {
    emits('finished');
  }
});

onMounted(() => {
  initCountUp();
  if (props.autoplay) {
    loopAnim();
  }
});

onUnmounted(() => {
  cancelAnimationFrame(dalayRafId);
  countUp.value?.reset();
});

let dalayRafId: number;
const delay = (cb: () => unknown, seconds = 1) => {
  let startTime: number;
  function count(timestamp: number) {
    if (!startTime) startTime = timestamp;
    const diff = timestamp - startTime;
    if (diff < seconds * 1000) {
      dalayRafId = requestAnimationFrame(count);
    } else {
      cb();
    }
  }
  dalayRafId = requestAnimationFrame(count);
};

const restart = () => {
  initCountUp();
  startAnim();
};

defineExpose({
  init: initCountUp,
  restart
});
</script>

<template>
  <div class="countup-wrap">
    <slot name="prefix"></slot>
    <span ref="elRef"> </span>
    <slot name="suffix">{{ formatted.suffix }}</slot>
  </div>
</template>